package logic

import (
	"context"
	"fmt"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"good_rpc/internal/svc"
	"good_rpc/models"
	"good_rpc/pb/good"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"

	"github.com/zeromicro/go-zero/core/logx"
)

type BatchStockTryLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewBatchStockTryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BatchStockTryLogic {
	return &BatchStockTryLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *BatchStockTryLogic) BatchStockTry(in *good.StockRequest) (*good.Empty, error) {
	goodQuery := "SELECT * FROM good WHERE id = ?"
	updateQuery := "UPDATE good SET version = version + 1 WHERE id = ? AND version = ?"
	err := l.svcCtx.Conn.TransactCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
		for _, v := range in.Stocks {
			// 查询当前商品信息
			var info models.Good
			err := session.QueryRowCtx(ctx, &info, goodQuery, v.GoodId)
			if err != nil {
				l.Logger.Errorf("BatchStock failed: good_id=%d, err: %v", v.GoodId, err)
				return fmt.Errorf("查询商品失败: %w", err)
			}

			// 检查库存
			if info.Stock < v.GoodCount {
				l.Logger.Errorf("BatchStock stock failed: good_id=%d, stock=%d, count=%d, err: %v", v.GoodId, info.Stock, v.GoodCount, err)
				return status.Error(codes.ResourceExhausted, "库存不足")
			}

			// 执行乐观锁更新
			result, err := session.ExecCtx(ctx, updateQuery, v.GoodId, info.Version)
			if err != nil {
				l.Logger.Errorf("BatchStock update stock failed: good_id=%d, err: %v", v.GoodId, err)
				return fmt.Errorf("更新库存失败: %w", err)
			}

			// 检查更新是否成功（版本是否匹配）
			rowsAffected, err := result.RowsAffected()
			if err != nil {
				l.Logger.Errorf("BatchStock update get affected failed: good_id=%d, err: %v", v.GoodId, err)
				return fmt.Errorf("获取更新行数失败: %w", err)
			}

			if rowsAffected == 0 {
				l.Logger.Errorf("BatchStock update abort failed: good_id=%d, err: %v", v.GoodId, err)
				return status.Error(codes.Aborted, "库存已被其他操作修改，请重试")
			}
		}
		return nil
	})
	if err == nil {
		return &good.Empty{}, nil // 成功提交事务
	}
	return &good.Empty{}, err
}
